﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Daphne.Modularity.UI;
using Daphne.GameShared;
using Daphne.Modularity.Commanding;
using Microsoft.Practices.Unity;
using Daphne.Modularity.Messaging;
using Daphne.SharedMetro;
using Windows.UI.Popups;
using Windows.UI.Xaml;


namespace Daphne.PagesMetro.ViewModels
{
    /// <summary>
    /// ViewModel for game editor
    /// TO-DO: implement region manager to inject viewmodels to the view / page, call initialized on viewmodel if required
    /// 3) region manager implementation
    /// 4) PagesModule and registration
    /// </summary>
    public class EditorPageVM: ViewModelBase, IInitialization
    {
        /// <summary>
        /// Contains color of figures currently being placed on the board
        /// </summary>
        private enumFigureColor _figuresToPlace;

        /// <summary>
        /// Reference to the gameboard interface
        /// </summary>
        [Dependency]
        protected IGameEditor GameEditor
        { get; set; }

        /// <summary>
        /// Constructor
        /// </summary>
        public EditorPageVM()
        {
            _figuresToPlace = enumFigureColor.White;

            // create commands
            FieldTappedCommand = new RelayCommand<Position>((pos) =>
            {
                PlaceFigure(pos);
                InvalidateView();
            });

            UndoCommand = new RelayCommand(() =>
            {
                GameEditor.Undo();
                InvalidateView();
            }, 
            () => { return GameEditor.CanUndo(); }
            );

            RedoCommand = new RelayCommand(() =>
            {
                GameEditor.Redo();
                InvalidateView();
            },
            () => { return GameEditor.CanRedo(); }
            );

            SetStartPositionCommand = new RelayCommand(() => 
            { 
                GameEditor.SetStartupPosition();
                InvalidateView();

            });

            ClearBoardCommand = new RelayCommand(() => 
            { 
                GameEditor.ClearBoard();
                InvalidateView();
            });

            AcceptPositionCommand = new RelayCommand(() => { AcceptPosition(); });
            CancelEditingCommand = new RelayCommand(() => { CancelEditing(); });
        }

        #region Binding Properties

        public RelayCommand<Position> FieldTappedCommand
        { get; set; }

        public RelayCommand UndoCommand
        { get; set; }

        public RelayCommand RedoCommand
        { get; set; }

        public RelayCommand SetStartPositionCommand
        { get; set; }

        public RelayCommand ClearBoardCommand
        { get; set; }

        public RelayCommand AcceptPositionCommand
        { get; set; }

        public RelayCommand CancelEditingCommand
        { get; set; }

        public bool WhiteFiguresChecked
        {
            get
            {
                return _figuresToPlace == enumFigureColor.White;
            }
            set
            {
                _figuresToPlace = enumFigureColor.White;
                RaisePropertyChanged(() => WhiteFiguresChecked);
                RaisePropertyChanged(() => BlackFiguresChecked);
            }
        }

        public bool BlackFiguresChecked
        {
            get
            {
                return _figuresToPlace == enumFigureColor.Black;
            }
            set
            {
                _figuresToPlace = enumFigureColor.Black;
                RaisePropertyChanged(() => WhiteFiguresChecked);
                RaisePropertyChanged(() => BlackFiguresChecked);
            }
        }

        public bool WhiteSTM
        {
            get
            {
                return GameEditor.GetSTM() == enumFigureColor.White;
            }
            set
            {
                GameEditor.SetSTM(enumFigureColor.White);
                RaisePropertyChanged(() => WhiteSTM);
                RaisePropertyChanged(() => BlackSTM);
            }
        }

        public bool BlackSTM
        {
            get
            {
                return GameEditor.GetSTM() == enumFigureColor.Black;
            }
            set
            {
                GameEditor.SetSTM(enumFigureColor.Black);
                RaisePropertyChanged(() => WhiteSTM);
                RaisePropertyChanged(() => BlackSTM);
            }
        }

        #endregion

        /// <summary>
        /// Command handler for placing figure
        /// </summary>
        private void PlaceFigure(Position pos)
        {
            // check, if white field
            if (GameEditor.GetFieldColor(pos) == enumFigureColor.White)
                return;

            // get figure on given field
            enumFigureType figureType = GameEditor.GetField(pos);

            // place the next figure
            GameEditor.PlaceFigure(pos, GetNextFigure(figureType));
        }

        /// <summary>
        /// Returns the next figure to be placed
        /// </summary>
        private enumFigureType GetNextFigure(enumFigureType figureType)
        {
            if(_figuresToPlace == enumFigureColor.White)
            {
                switch(figureType)
                {
                    case enumFigureType.WhiteMan:
                        return enumFigureType.WhiteKing;
                    case enumFigureType.WhiteKing:
                        return enumFigureType.Nothing;
                    default:
                        return enumFigureType.WhiteMan;
                }
            }
            else
            {
                switch(figureType)
                {
                    case enumFigureType.BlackMan:
                        return enumFigureType.BlackKing;
                    case enumFigureType.BlackKing:
                        return enumFigureType.Nothing;
                    default:
                        return enumFigureType.BlackMan;
                }
            }
        }

        /// <summary>
        /// Final button to accept set-up position
        /// </summary>
        private void AcceptPosition()
        {
            // TO-DO: how to delete moves??? whose responsibility

            // notify to go to the main page
            Messenger.Send<LeavePageMessage>(new LeavePageMessage());
        }

        /// <summary>
        /// Show message box and cancels editing
        /// </summary>
        async private void CancelEditing()
        {
            // restores the position
            GameEditor.RestorePreviousPosition();

            // confirm the page leaving from the user
            MessageDialog dlg = new MessageDialog("Opravdu chcete zrušit editaci šachovnice?", "Ukončení editoru pozic");
            UICommand okCmd = new UICommand("OK"); 
            dlg.Commands.Add(okCmd);
            dlg.Commands.Add(new UICommand("Storno"));
            IUICommand result = await dlg.ShowAsync();

            // check result
            if (result == okCmd)
            {
                // notify to go to the main page
                Messenger.Send<LeavePageMessage>(new LeavePageMessage());
            }           
        }

        /// <summary>
        /// Initialization
        /// </summary>
        public void OnInitialized()
        {
            // clear editor internals and prepare for the next editing show
            GameEditor.NotifyEditModeStarted();
        }

        /// <summary>
        /// Invalidates view
        /// </summary>
        private void InvalidateView()
        {
            // send message to update board
            Messenger.Send<RedrawBoard>(new RedrawBoard());

            // update undo / redo
            UndoCommand.RaiseCanExecuteChanged();
            RedoCommand.RaiseCanExecuteChanged();
        }
    }
}
